"""
Case Type   : openGauss-tools-backup
Case Name   : 导出时注入磁盘满故障，再进行导入
Create At   : 2022/01/18
Owner       : z@wan005
Description :
        1.创建工具目录
        2.获取工具安装包并解压
        3.创建数据库
        4.指定数据库下创建测试用户及建表
        5.配置白名单
        6.注入磁盘满故障
        7.导出指定数据库
        8.清除故障
        9.删除表
        10.导入
        11.查看表数据
        12.再次导出
        13.删表
        14.导入
        15.查询表数据
        16.清理环境
Expect      :
        1.创建成功
        2.解压成功
        3.创建成功
        4.创建成功
        5.配置成功
        6.成功
        7.导出报错，空间不足
        8.成功
        9.删除成功
        10.导入失败
        11.表不存在
        12.导出成功
        13.删表成功
        14.导入成功
        15.表数据正确
        16.清理环境完成
History     : modified by z@wan005,2022.03.08，修改用例方法
            modified by z@wan005,2022.04.06，修改用例断言方法名
            modified by z@wan005,2022.04.13，修改用例使用的变量名
            modified by z@wan005,2022.05.23，修改断言及清除故障后增加重启数据库操作
"""
import os
import time
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class ToolsBackup(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.constant = Constant()
        self.Primary_Node = Node('PrimaryDbUser')
        self.pri_root = Node(node='PrimaryRoot')
        self.package = os.path.join(
            os.path.dirname(macro.DB_INSTANCE_PATH), 'package_tool')
        self.tools_path = os.path.join(os.path.dirname(macro.FTP_TOOLS_PATH),
                                       'tools',
                                       'openGauss-tools-backup.tar.gz')
        self.db_name = "db_jdbcgsbackup0001"
        self.user = "u_jdbcgsbackup0001"
        self.tb_name = "t_jdbcgsbackup0001"
        self.tb_name_01 = "t_jdbcgsbackup0001_01"
        self.compri = Common('PrimaryRoot')
        self.db_disk_name = self.compri.get_disk_name(macro.DB_INSTANCE_PATH)
        self.inject_cmd = f"rfile_full (diskname) values ({self.db_disk_name})"
        self.clean_cmd = f"rfile_full  where(diskname={self.db_disk_name})"

    def test_tools_backup(self):
        text = '---step1:创建工具所在目录;expect:创建成功---'
        self.log.info(text)
        mkdir_cmd = f'''if [ ! -d "{self.package}" ]
                        then
                            mkdir -p {self.package}
                        fi'''
        self.log.info(mkdir_cmd)
        result = self.Primary_Node.sh(mkdir_cmd).result()
        self.log.info(result)
        self.assertEqual(result, '', '执行失败:' + text)

        text = '---step2:获取openGauss-tools-backup工具包并解压;' \
               'expect:解压成功---'
        self.log.info(text)
        sql_cmd = f"wget -P {self.package} {self.tools_path};" \
                  f"cd {self.package};" \
                  f"tar -zxvf openGauss-tools-backup.tar.gz;"
        self.log.info(sql_cmd)
        result = self.Primary_Node.sh(sql_cmd).result()
        self.log.info(result)
        self.assertIn(f"‘{self.package}/openGauss-tools-backup.tar.gz’ saved"
                      , result, '执行失败:' + text)

        text = '---step3:创建数据库和用户;expect:创建成功---'
        self.log.info(text)
        sql_cmd = self.pri_sh.executDbSql(f"drop database if exists "
                                          f"{self.db_name};"
                                          f"create database {self.db_name};"
                                          f"drop user if exists {self.user};"
                                          f"create user {self.user} with "
                                          f"sysadmin password "
                                          f"'{macro.PASSWD_INITIAL}';")
        self.log.info(sql_cmd)
        self.assertIn(self.constant.CREATE_DATABASE_SUCCESS_MSG, sql_cmd,
                      '执行失败:' + text)
        self.assertIn(self.constant.CREATE_ROLE, sql_cmd,
                      '执行失败:' + text)

        text = '---step4:建表;expect:创建成功---'
        self.log.info(text)
        sql_cmd = f"drop table if exists {self.tb_name};" \
                  f"create table {self.tb_name} (id int);" \
                  f"insert into {self.tb_name} values(1),(2),(3);" \
                  f"create table {self.tb_name_01} (id int);" \
                  f"insert into {self.tb_name_01} values(1),(2),(3);"
        self.log.info(sql_cmd)
        sql_result = self.pri_sh.executDbSql(sql=sql_cmd,
                                             dbname=f'{self.db_name}')
        self.log.info(sql_result)
        self.assertIn(self.constant.TABLE_CREATE_SUCCESS, sql_result,
                      '执行失败:' + text)

        text = '---step5:配置白名单;expect:配置成功---'
        self.log.info(text)
        guc_cmd = f'source {macro.DB_ENV_PATH};' \
                  f'gs_guc reload -D {macro.DB_INSTANCE_PATH} ' \
                  f'-h "host {self.db_name}  {self.user}  ' \
                  f'{self.Primary_Node.db_host}/32 sha256"'
        self.log.info(guc_cmd)
        guc_res = self.Primary_Node.sh(guc_cmd).result()
        self.log.info(guc_res)
        self.assertIn(self.constant.GSGUC_SUCCESS_MSG, guc_res,
                      '执行失败:' + text)

        text = '---step6:注入磁盘满故障;expect:成功---'
        self.log.info(text)
        inject_cmd = f'rfile_full (diskname) values ({self.db_disk_name})'
        inject_result = self.compri.cfe_inject(self.pri_root, inject_cmd)
        self.log.info(inject_result)
        self.assertIn("successful execution", inject_result, '执行失败:' + text)

        text = '---step7:导出指定数据库;expect:导出失败---'
        self.log.info(text)
        sql_cmd = f"cd {self.package}/openGauss-tools-backup;" \
                  f"java -jar openGauss-tools-backup.jar " \
                  f" -m dump " \
                  f"-d {self.db_name} " \
                  f"-h {self.Primary_Node.db_host} " \
                  f"-p {self.Primary_Node.db_port} " \
                  f" -U {self.user} " \
                  f"-P {macro.PASSWD_INITIAL} " \
                  f"-s public "
        self.log.info(sql_cmd)
        msg = self.Primary_Node.sh(sql_cmd).result()
        self.log.info(msg)
        self.assertIn('backup failed', msg, '执行失败:' + text)

        text = '---step8:清除故障;expect:成功----'
        self.log.info(text)
        clean_cmd = f'rfile_full where(diskname={self.db_disk_name})'
        clean_result = self.compri.cfe_clean(self.pri_root, clean_cmd)
        self.log.info(clean_result)
        self.pri_sh.stopDbCluster()
        time.sleep(2)
        self.pri_sh.startDbCluster()
        status = self.pri_sh.getDbClusterStatus('status')
        self.log.info(status)
        self.assertTrue(status)

        text = '---step9:删除表;expect:删除成功---'
        self.log.info(text)
        sql_cmd = f"drop table {self.tb_name};"
        sql_result = self.pri_sh.executDbSql(sql=sql_cmd,
                                             dbname=f'{self.db_name}')
        self.log.info(sql_result)
        self.assertIn(self.constant.DROP_TABLE_SUCCESS, sql_result,
                      '执行失败:' + text)

        text = '---step10:导入;expect:导入失败---'
        self.log.info(text)
        sql_cmd = f'''cd {self.package}/openGauss-tools-backup;\
            java -jar openGauss-tools-backup.jar \
            -m restore \
            -d {self.db_name} \
            -h {self.Primary_Node.db_host} \
            -p {self.Primary_Node.db_port} \
            -U {self.user} \
            -P {macro.PASSWD_INITIAL} \
            -s public \
            -n public'''
        self.log.info(sql_cmd)
        msg = self.Primary_Node.sh(sql_cmd).result()
        self.log.info(msg)
        self.assertIn('No such file or directory', msg, '执行失败:' + text)

        text = '---step11:查询表;expect:表不存在---'
        self.log.info(text)
        sql_cmd = f"select count(*) from {self.tb_name};"
        sql_result = self.pri_sh.executDbSql(sql=sql_cmd,
                                             dbname=f'{self.db_name}')
        self.log.info(sql_result)
        self.assertIn(f'ERROR:  relation "{self.tb_name}" does not exist',
                      sql_result, '执行失败:' + text)

        text = '---step12:再次导出指定数据库;expect:导出成功---'
        self.log.info(text)
        sql_cmd = f"cd {self.package}/openGauss-tools-backup;" \
                  f"java -jar openGauss-tools-backup.jar " \
                  f" -m dump " \
                  f"-d {self.db_name} " \
                  f"-h {self.Primary_Node.db_host} " \
                  f"-p {self.Primary_Node.db_port} " \
                  f" -U {self.user} " \
                  f"-P {macro.PASSWD_INITIAL} " \
                  f"-s public "
        self.log.info(sql_cmd)
        msg = self.Primary_Node.sh(sql_cmd).result()
        self.log.info(msg)
        self.assertIn(self.constant.jdbcgsbackup_success, msg,
                      '执行失败:' + text)
        self.assertNotIn(self.constant.jdbcgsbackup_failed[0] and
                         self.constant.jdbcgsbackup_failed[1] and
                         self.constant.jdbcgsbackup_failed[2], msg,
                         '执行失败:' + text)

        text = '---step13:删除表;expect:删除成功---'
        self.log.info(text)
        sql_cmd = f"drop table {self.tb_name_01};"
        sql_result = self.pri_sh.executDbSql(sql=sql_cmd,
                                             dbname=f'{self.db_name}')
        self.log.info(sql_result)
        self.assertIn(self.constant.DROP_TABLE_SUCCESS, sql_result,
                      '执行失败:' + text)

        text = '---step14:导入;expect:导入成功---'
        self.log.info(text)
        sql_cmd = f'''cd {self.package}/openGauss-tools-backup;\
            java -jar openGauss-tools-backup.jar \
            -m restore \
            -d {self.db_name} \
            -h {self.Primary_Node.db_host} \
            -p {self.Primary_Node.db_port} \
            -U {self.user} \
            -P {macro.PASSWD_INITIAL} \
            -s public \
            -n public'''
        self.log.info(sql_cmd)
        msg = self.Primary_Node.sh(sql_cmd).result()
        self.log.info(msg)
        self.assertIn(self.constant.jdbcgsbackup_success, msg,
                      '执行失败:' + text)
        self.assertNotIn(self.constant.jdbcgsbackup_failed[0] and
                         self.constant.jdbcgsbackup_failed[1] and
                         self.constant.jdbcgsbackup_failed[2], msg,
                         '执行失败:' + text)

        text = '---step15:查询表;expect:表数据正确---'
        self.log.info(text)
        sql_cmd = f"select count(*) from {self.tb_name_01};"
        sql_result = self.pri_sh.executDbSql(sql=sql_cmd,
                                             dbname=f'{self.db_name}')
        self.log.info(sql_result)
        self.assertEqual('3', sql_result.splitlines()[-2].strip(),
                         '执行失败:' + text)

    def tearDown(self):
        text = '---step16:清理环境;expect:清理环境成功---'
        self.log.info(text)
        clean_cmd = f'rfile_full where(diskname={self.db_disk_name})'
        clean_result = self.compri.cfe_clean(self.pri_root, clean_cmd)
        self.log.info(clean_result)
        self.pri_sh.stopDbCluster()
        time.sleep(2)
        self.pri_sh.startDbCluster()
        status = self.pri_sh.getDbClusterStatus('status')
        self.log.info(status)

        rm_cmd = f"rm -rf {self.package};"
        self.log.info(rm_cmd)
        rm_result = self.Primary_Node.sh(rm_cmd).result()
        self.log.info(rm_result)

        guc_cmd = f'source {macro.DB_ENV_PATH};' \
                  f'gs_guc reload -D {macro.DB_INSTANCE_PATH} ' \
                  f'-h "host {self.db_name}  {self.user}  ' \
                  f'{self.Primary_Node.db_host}/32"'
        self.log.info(guc_cmd)
        guc_result = self.Primary_Node.sh(guc_cmd).result()
        self.log.info(guc_result)
        drop_cmd = self.pri_sh.executDbSql(f"drop database if exists "
                                           f"{self.db_name};"
                                           f"drop user if exists "
                                           f"{self.user} cascade;")
        self.log.info(drop_cmd)

        self.log.info('断言teardown成功')
        self.assertIn("successful execution", clean_result, '执行失败:' + text)
        self.assertTrue(status, '执行失败:' + text)
        self.assertEqual(len(rm_result), 0, '执行失败:' + text)
        self.assertIn(self.constant.GSGUC_SUCCESS_MSG, guc_result,
                      '执行失败:' + text)
        self.assertTrue(
            self.constant.drop_database_success_msg in drop_cmd and
            self.constant.drop_role_success_msg in drop_cmd,
            '执行失败:' + text)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
